package it.polimi.entitiesManagers;

import java.util.ArrayList;
import java.util.List;

import it.polimi.authentication.ejb.usermanagement.Group;
import it.polimi.entities.Airport;
import it.polimi.entities.Flight;
import it.polimi.entities.Hotel;
import it.polimi.entitiesDTO.AirportDTO;
import it.polimi.entitiesDTO.FlightDTO;

import javax.annotation.Resource;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJBContext;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class TransportManagerBean implements TransportMgr {


	@PersistenceContext
    private EntityManager em;
	
	@Resource
	private EJBContext context;
	
	@Override
	@RolesAllowed({Group._EMPLOYEE})
	public void save(AirportDTO airport){
		Airport newAirport = new Airport(airport);
		em.persist(newAirport);
	}

	public void update(AirportDTO airport){
		em.merge(new Airport(airport));
	}
	
	public AirportDTO getAirportDTO(){
		AirportDTO airportDTO = convertToDTO(getPrincipalAirport());
		return airportDTO;
	}
	
	public Airport findAirport(String name) {
    	return em.find(Airport.class, name);
    }
	
	public Airport getPrincipalAirport() {
    	return findAirport(getPrincipalName());
    }
	
	public String getPrincipalName() {
    	return context.getCallerPrincipal().getName();
    }
	
	public Airport getAirport(String name){
		return em.createNamedQuery(Airport.FIND_AIRPORT, Airport.class).setParameter("name", name).getSingleResult();
	}

    
    private AirportDTO convertToDTO(Airport airport) {
		AirportDTO airportDTO = new AirportDTO();
		airportDTO.setName(airport.getName());
		airportDTO.setCity(airport.getCity());
		return airportDTO;
	}
    
    @Override
	@RolesAllowed(Group._EMPLOYEE)
	public void save(FlightDTO flightDTO) {
		Airport arrivalAirport = getAirport(flightDTO.getArrival_airport());
		Airport departureAirport = getAirport(flightDTO.getDeparture_airport());
		Flight flight = new Flight(flightDTO, departureAirport, arrivalAirport);
		em.persist(flight);
	}

	@Override
	public void update(FlightDTO flight) {
		em.merge(new Flight(flight,getAirport(flight.getArrival_airport()),getAirport(flight.getDeparture_airport())));
	}

	@Override
	public FlightDTO getFlightDTO() {
		FlightDTO flightDTO = convertToDTO(getPrincipalFlight());
		return flightDTO;
	}
	
	public Flight findFlight(String name) {
    	return em.find(Flight.class, name);
    }
	
	public Flight getPrincipalFlight() {
    	return findFlight(getPrincipalName());
    }
	
	
	public Flight getFlight(String id){
		return em.createNamedQuery(Flight.FIND_FLIGHT, Flight.class).setParameter("id", id).getSingleResult();
	}

    
private FlightDTO convertToDTO(Flight flight) {
		FlightDTO flightDTO = new FlightDTO();
		flightDTO.setDeparture_airport(flight.getAirport1().getName());
		flightDTO.setArrival_airport(flight.getAirport2().getName());
		flightDTO.setClass_(flight.getClass_());
		flightDTO.setPrice(flight.getPrice());
		flightDTO.setSpots(flight.getSpots());
		flightDTO.setVisibility(flight.getVisibility());
		return flightDTO;
	}


public List<Airport> findAllAirports(){
	return em.createNamedQuery(Airport.FIND_ALL, Airport.class).getResultList();
}

public List<String> findFlightByArrival(String city){
	
	List<Airport> cityAirports = new ArrayList<Airport>();
	List<String> list = new ArrayList<String>();
	
	for(Airport a: airportByCity(city))
		cityAirports.add(a);
	
	for(Airport a: cityAirports){
		for(Flight f: flightByArrivalAirport(a.getName()))
			list.add(f.toString());
	}
	return list;
		}



@Override
public List<String> findFlightByDeparture(String city) {
	
	List<Airport> cityAirports = new ArrayList<Airport>();
	List<String> list = new ArrayList<String>();
	
	for(Airport a: airportByCity(city))
		cityAirports.add(a);
	
	for(Airport a: cityAirports){
		for(Flight f: flightByDepartureAirport(a.getName()))
			list.add(f.toString());
	}
	
	return list;
		}
	

private List<Flight> getAllFlights(){
	return em.createNamedQuery(Flight.FIND_ALL, Flight.class).getResultList();
}

@Override
public List<String> findAllAirport() {
	List<String> list = new ArrayList<String>();
	for (Airport a: findAllAirports()){
		list.add(a.getName());
	}
	return list;
	
}
	


public List<String> findFlightByAirport(String airport){
	
	List<String> list = new ArrayList<String>();
	
	for(Flight f: flightByDepartureAirport(airport))
		list.add(f.toString());
	
	return list;
		}


private List<Flight> flightByDepartureAirport(String airport){
	return em.createNamedQuery(Flight.FIND_FLIGHT_BY_DEPARTURE, Flight.class).setParameter("airport1", airport).getResultList();
}

private List<Flight> flightByArrivalAirport(String airport){
	return em.createNamedQuery(Flight.FIND_FLIGHT_BY_ARRIVAL, Flight.class).setParameter("airport2", airport).getResultList();
}

private List<Airport> airportByCity(String city){
	return em.createNamedQuery(Airport.FIND_AIRPORT_BY_CITY, Airport.class).setParameter("city", city).getResultList();
}

@Override
public List<String> showAllAirport() {
	List<String> list = new ArrayList<String>();
	List<Airport> air = em.createNamedQuery(Airport.FIND_ALL, Airport.class).getResultList();
	for (Airport a : air){
		list.add(a.toString());
	}
	return list;
}

@Override
public List<String> findAllFlight() {
	List<String> list = new ArrayList<String>();
	List<Flight> fl = em.createNamedQuery(Flight.FIND_ALL, Flight.class).getResultList();
	for (Flight a : fl){
		if(a.getVisibility())
		list.add(a.toString());
	}
	return list;
}

@Override
public List<Integer> findAllId() {
	List<Integer> list = new ArrayList<Integer>();
	List<Flight> fl = em.createNamedQuery(Flight.FIND_ALL, Flight.class).getResultList();
	for(Flight f : fl){
		list.add((Integer)f.getId());
	}
	return list;
}

@Override
public void remove(int id) {
 Flight f = em.createNamedQuery(Flight.FIND_FLIGHT, Flight.class).setParameter("id", id).getSingleResult();
 em.remove(f);
	
}




}